﻿#include "XCompareDir.h"

#define _DEFAULT_COMPARE_SIZE_ (1024*10)

/***********************************************************************************************************************/
//
//	TODO: 
//	1.界面设计与实现
//	2.win32 API效率不够  需要直接读取文件系统   优先级降低
//
/***********************************************************************************************************************/

//QString CRC64(const QString &inputStr)
//{
//	boost::crc_optimal<64, 0x42F0E1EBA9EA3693,
//		0xffffffffffffffff, 0xffffffffffffffff,
//		false, false> crc;
//
//	crc.process_bytes(inputStr.constData(), inputStr.size());
//
//	char crcStr[128] = { 0 };
//	sprintf_s(crcStr, 128, "%016llx", crc.checksum());
//	return crcStr;
//}

qulonglong CRC64(const QByteArray &inputStr)
{
	boost::crc_optimal<64, 0x42F0E1EBA9EA3693,
		0xffffffffffffffff, 0xffffffffffffffff,
		false, false> crc;

	crc.process_bytes(inputStr.constData(), inputStr.size());
	return crc.checksum();
}

void showSubFile(const QDir & dir)
{
	// TODO:显示顺序调整为windows系统顺序  Low Priority
	auto leftFileList = dir.entryInfoList(QDir::NoDotAndDotDot | QDir::AllEntries, QDir::Name);
	for (auto info : leftFileList)
	{
		if (info.isDir())
		{
			//qDebug() << info.absoluteFilePath();
		}
		else
		{
			QFile file(info.absoluteFilePath());
			if (!file.open(QIODevice::ReadOnly))
			{
				qDebug() << info.absoluteFilePath() << " Open Failed!";
				continue;
			}
			int nSize = (_DEFAULT_COMPARE_SIZE_ > info.size()) ? info.size() : _DEFAULT_COMPARE_SIZE_;
			auto data = file.read(nSize);
			auto nCrc = qChecksum(data.constData(), nSize);
			qDebug() << info.absoluteFilePath() << " Crc: " << CRC64(data);
		}
	}
}

void XCompareDir::Work()
{
	QDir dirLeft(m_strLeft);
	QDir dirRight(m_strRight);
	// TODO:显示顺序调整为windows系统顺序  Low Priority
	auto leftFileList = dirLeft.entryInfoList(QDir::NoDotAndDotDot | QDir::AllEntries, QDir::Name | QDir::DirsLast);
	auto rightFileList = dirRight.entryInfoList(QDir::NoDotAndDotDot | QDir::AllEntries, QDir::Name | QDir::DirsLast);

	// TODO:显示到界面


	// TOOD:遍历对比 分别出相同  不同  一方不存在情况
	auto leftCrcList = GetCrcList(leftFileList);
	auto rightCrcList = GetCrcList(rightFileList);

	auto leftCheckList = GetCheckList(leftCrcList, rightCrcList);
	auto rightCheckList = GetCheckList(rightCrcList, leftCrcList);
	qDebug() << "left:" << m_strLeft;
	//show(leftCheckList);
	qDebug() << "right:" << m_strRight;
	//show(rightCheckList);

	// TODO:不同显示  相同显示  一方不存在显示
	qDebug() << "end";
}

QVariantList XCompareDir::Compare()
{
	//qDebug() << "===" << m_strLeft << m_strRight;
	QDir dirLeft(m_strLeft);
	QDir dirRight(m_strRight);
	// TODO:显示顺序调整为windows系统顺序  Low Priority
	auto leftFileList = dirLeft.entryInfoList(QDir::NoDotAndDotDot | QDir::AllEntries, QDir::Name | QDir::DirsLast);
	auto rightFileList = dirRight.entryInfoList(QDir::NoDotAndDotDot | QDir::AllEntries, QDir::Name | QDir::DirsLast);

	// TODO:显示到界面


	// TOOD:遍历对比 分别出相同  不同  一方不存在情况
	auto leftCrcList = GetCrcList(leftFileList);
	auto rightCrcList = GetCrcList(rightFileList);

	auto leftCheckList = GetCheckList(leftCrcList, rightCrcList);
	auto rightCheckList = GetCheckList(rightCrcList, leftCrcList);

	QVariantList li;
	li.push_back(leftCheckList);
	li.push_back(rightCheckList);

	return li;
}

//bool XCompareDir::IsNull()
//{
//	return m_strLeft.isEmpty()|| m_strRight.isEmpty();
//}

bool XCompareDir::GetCrc(QFileInfo & info, qulonglong & crc)
{
	if (info.isDir())
	{
		//return GetDirCrc(info, crc);
		qDebug() << info.absoluteFilePath();
	}
	else
	{
		QFile file(info.absoluteFilePath());
		if (!file.open(QIODevice::ReadOnly))
		{
			qDebug() << info.absoluteFilePath() << " Open Failed!";
			return false;
		}
		int nSize = (_DEFAULT_COMPARE_SIZE_ > info.size()) ? info.size() : _DEFAULT_COMPARE_SIZE_;
		auto data = file.read(nSize);
		//crc = qChecksum(data.constData(), nSize);
		crc = CRC64(data);
	}
	return true;
}

bool XCompareDir::GetDirCrc(QFileInfo info, qulonglong & crc)
{
	QDir dir(info.absoluteFilePath());
	auto fileList = dir.entryInfoList(QDir::NoDotAndDotDot | QDir::AllEntries, QDir::Name);
	/*auto hx = fileList.size();*/
	for (auto infoSub : fileList)
	{
		qulonglong nTmpCrc = 0;
		GetCrc(infoSub, nTmpCrc);
		crc += nTmpCrc;
	}
	return true;
}

FileInfoCrcList XCompareDir::GetCrcList(QFileInfoList & infoList)
{
	FileInfoCrcList tmp;
	for (auto info : infoList)
	{
		qulonglong nCrc = 0;
		if (GetCrc(info, nCrc))
		{
			CrcType tmpValue(info, nCrc);
			tmp.push_back(tmpValue);
			//tmp[info.absoluteFilePath()] = nCrc;
		}
		else
		{
			// TODO： 未打开文件处理
		}
	}
	return tmp;
}

// now is current compare, the result is now compare tmp;
//FileInfoCheckList XCompareDir::GetCheckList(FileInfoCrcList leftList, FileInfoCrcList rightList)
//{
//	FileInfoCheckList left;
//	for (auto pairLeft : leftList)
//	{
//		auto iterName = pairLeft.first.fileName();
//		auto findResult = rightList.end();
//		for (auto iterRight = rightList.begin(); iterRight != rightList.end(); ++iterRight)
//		{
//			QString name = iterRight->first.fileName();
//			if (0 == name.compare(iterName, Qt::CaseInsensitive))
//			{
//				findResult = iterRight;
//				break;
//			}
//		}
//		if (findResult == rightList.end())
//		{
//			CheckType tmpValue(pairLeft.first, File_NoExist);
//			left.push_back(tmpValue);
//			//left[iter.key()] = File_NoExist;
//			continue;
//		}
//
//		if (findResult->second == pairLeft.second)
//		{
//			CheckType tmpValue(pairLeft.first, File_Equal);
//			left.push_back(tmpValue);
//		}
//		else
//		{
//			CheckType tmpValue(pairLeft.first, File_Difference);
//			left.push_back(tmpValue);
//		}
//	}
//
//	return left;
//}

QVariant XCompareDir::GetCheckList(FileInfoCrcList leftList, FileInfoCrcList rightList)
{
	QVariantList result;
	int n = 0;
	for (auto pairLeft : leftList)
	{
		QVariantList listTmp;
		QString strTmp = QString::number(n++);
		auto iterName = pairLeft.first.fileName();
		auto findResult = rightList.end();
		for (auto iterRight = rightList.begin(); iterRight != rightList.end(); ++iterRight)
		{
			QString name = iterRight->first.fileName();
			if (0 == name.compare(iterName, Qt::CaseInsensitive))
			{
				findResult = iterRight;
				break;
			}
		}
		if (findResult == rightList.end())
		{
			listTmp.push_back(QVariant::fromValue(pairLeft.first));
			listTmp.push_back(QVariant::fromValue(XFile_NoExist));
			result.push_back(listTmp);
			//left[iter.key()] = File_NoExist;
			continue;
		}

		if (findResult->second == pairLeft.second)
		{
			listTmp.push_back(QVariant::fromValue(pairLeft.first));
			listTmp.push_back(QVariant::fromValue(XFile_Equal));
			listTmp.push_back(QVariant::fromValue(findResult->first));
			result.push_back(listTmp);
		}
		else
		{
			listTmp.push_back(QVariant::fromValue(pairLeft.first));
			listTmp.push_back(QVariant::fromValue(XFile_Difference));
			listTmp.push_back(QVariant::fromValue(findResult->first));
			result.push_back(listTmp);
		}
	}

	return result;
}